#include "socket_private_acl.h"
#include "pfunc.h"
#include "Log.h"
#include "lib_acl.h"

SocketPrivate_ACL::SocketPrivate_ACL(unsigned int port,std::string ip/*="0.0.0.0"*/)
	: m_Port(port)
{
	char buf[128] = { 0 };
	sprintf(buf, "%s:%d", ip.c_str(),m_Port);
	addr = acl::string(buf);
	m_CSockets.clear();
	m_OnListen = false;
	newlinkF = false;
};
SocketPrivate_ACL::~SocketPrivate_ACL() {
	disConnect();
};

int SocketPrivate_ACL::onConnect()
{
	acl::acl_cpp_init();
	if (m_SSocket.open(addr) == false)
	{
		Print_WARN("open %s error %s\r\n", addr.c_str(), acl::last_serror());
		return 0;
	}
	else {
		m_OnListen = true;
		Print_NOTICE("open %s ok\r\n", addr.c_str());
		return 1;
	}
}

void SocketPrivate_ACL::disConnect()
{
	try {
		m_MyMutex.Lock();
		std::map<KeyObj_Client, ClientSOCKET_ACL>::iterator it = m_CSockets.begin();
		while (it != m_CSockets.end())
		{
			close_client(it->second.client);
#ifdef WIN32
			it = m_CSockets.erase(it);
#else
			std::map<KeyObj_Client, ClientSOCKET_ACL>::iterator ittemp = it++;
			m_CSockets.erase(ittemp);
#endif
		}
		m_MyMutex.Unlock();
	}
	catch (...)
	{
		CLogger::createInstance()->Log(MsgError,
			"socket deleteCSockets exception: [%s %s %d]!"
			, __FILE__, __FUNCTION__, __LINE__);
	}
	m_OnListen = false;
	if (m_SSocket.close() == false)
	{
		CLogger::createInstance()->Log(MsgError
			, "close %s error", addr.c_str());
	}
}

void SocketPrivate_ACL::close_client(acl::socket_stream* client_acl)
{
	if(NULL==client_acl){
		return;
	}
	if(!client_acl->close())
	{
		CLogger::createInstance()->Log(MsgError
			, "close client_acl error[%d,%s]"
			, acl_last_error()
			, acl::last_serror());
	}
	delete client_acl;
	client_acl = NULL;
}

bool SocketPrivate_ACL::emptyClients()
{
	bool ret = false;
	m_MyMutex.Lock();
	ret = m_CSockets.empty();
	m_MyMutex.Unlock();
	return ret;
}

bool SocketPrivate_ACL::getNewAddClient(std::vector<unsigned long long> &ips)
{
	if (!newlinkF)
	{
		return false;
	}
	m_MyMutex.Lock();
	std::map<KeyObj_Client, ClientSOCKET_ACL>::iterator it = m_CSockets.begin();
	while (it != m_CSockets.end())
	{
		if (it->second.flag <= 0)
		{
			ips.push_back(it->first.m_ip);
			it->second.flag = 1;
		}
		it++;
	}
	m_MyMutex.Unlock();
	newlinkF = false;
	return !ips.empty();
}

int SocketPrivate_ACL::Read(std::map<KeyObj_Client, RDClient> &bufs)
{
	int re = 0;
	try {
		m_MyMutex.Lock();
		std::map<KeyObj_Client, ClientSOCKET_ACL>::iterator it = m_CSockets.begin();
		while (it != m_CSockets.end())
		{
			char _buf[512] = { 0 };
			acl::string res;
			int len = it->second.client->read(_buf, 512,false);
			if (len<0)
			{
				int lerror = acl_last_error();
				//win 10060 timeout,linux 110 timeout
				if (lerror != 10060 
					// && lerror !=110 
					&& lerror !=11
					// && lerror != 0
					)
				{
					CLogger::createInstance()->Log(MsgWarn,
						"socket read data failed[%d,%s]! return val is %d.[%s %s %d]"
						, lerror,acl::last_serror(), len, __FILE__, __FUNCTION__, __LINE__);
					close_client(it->second.client);
#ifdef WIN32
					it = m_CSockets.erase(it);
#else
					std::map<KeyObj_Client, ClientSOCKET_ACL>::iterator ittemp = it++;
					m_CSockets.erase(ittemp);
#endif
					continue;
				}
			}
			if (len>0)
			{
				re += len;
				std::map<KeyObj_Client, RDClient>::iterator itrd = bufs.find(it->first);
				if (itrd != bufs.end())
				{
					itrd->second.add((unsigned char*)_buf, len);
				}
				else
				{
					bufs[it->first] = RDClient((unsigned char*)_buf, len);
				}
			}

			it++;
		}
		m_MyMutex.Unlock();

	}
	catch (...)
	{
		CLogger::createInstance()->Log(MsgError,
			"Read Data Failed!unknown error! [%s %s %d]"
			, __FILE__, __FUNCTION__, __LINE__);
		re = -1;
	}
	return re;
}

int SocketPrivate_ACL::Write(const char* buf, int size)
{
	int re = -1;
	try {
		m_MyMutex.Lock();
		std::map<KeyObj_Client, ClientSOCKET_ACL>::iterator it = m_CSockets.begin();
		while (it != m_CSockets.end())
		{
			re = it->second.client->write(buf, size);
			if (re < 0)
			{
				int lerror = acl_last_error();
				if (lerror != 0)
				{
					//CLogger willadd datetime for log, and the time difference is very small
					CLogger::createInstance()->Log(MsgWarn,
						"socket write data failed! "
						"return val is %d,%s.[%s %s %d]"
						, re, buf
						, __FILE__, __FUNCTION__, __LINE__);
					close_client(it->second.client);
#ifdef WIN32
					it = m_CSockets.erase(it);
#else
					std::map<KeyObj_Client, ClientSOCKET_ACL>::iterator ittemp = it++;
					m_CSockets.erase(ittemp);
#endif
					continue;
				}
			}
			it++;
		}
		m_MyMutex.Unlock();
	}
	catch (...)
	{
		CLogger::createInstance()->Log(MsgError,
			"Write Data Failed!unknown error![%s %s %d]"
			, __FILE__, __FUNCTION__, __LINE__);
		re = -1;
	}
	return re;
}

int SocketPrivate_ACL::Write(unsigned long long ipInt, const char* buf, int size, bool &mapIpF)
{
	int re = -1;
	mapIpF = false;
	try {
		m_MyMutex.Lock();
		std::map<KeyObj_Client, ClientSOCKET_ACL>::iterator it = m_CSockets.begin();
		while (it != m_CSockets.end())
		{
			if (ipInt == it->first.m_ip)
			{
				mapIpF = true;
				re = it->second.client->write(buf, size);
				if (re < 0)
				{
					int lerror = acl_last_error();
					if (lerror != 0)
					{
						//CLogger willadd datetime for log
						CLogger::createInstance()->Log(MsgWarn,
							"socket write data failed! "
							"return val is %d,%s.[%s %s %d]"
							, re, buf
							, __FILE__, __FUNCTION__, __LINE__);
						close_client(it->second.client);
#ifdef WIN32
						it = m_CSockets.erase(it);
#else
						std::map<KeyObj_Client, ClientSOCKET_ACL>::iterator ittemp = it++;
						m_CSockets.erase(ittemp);
#endif
						continue;
					}
				}
			}
			it++;
		}
		m_MyMutex.Unlock();
	}
	catch (...)
	{
		CLogger::createInstance()->Log(MsgError,
			"Write Data Failed!unknown error![%s %s %d]"
			, __FILE__, __FUNCTION__, __LINE__);
		re = -1;
	}
	return re;
}

bool SocketPrivate_ACL::Accept()
{
	if (!m_OnListen)
		return false;
	acl::socket_stream* client = m_SSocket.accept();
	if (client != NULL)
	{
		#ifdef WIN32
		SOCKET sock_fd = client->sock_handle();
		int nNetTimeout = 10; //10毫秒
		setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&nNetTimeout, sizeof(int));
		setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout, sizeof(int));
		#else
		client->set_tcp_non_blocking(true);
		// client->set_tcp_nodelay(true);
		// client->set_rw_timeout(1);
		#endif
		ClientSOCKET_ACL newLink;
		newLink.client = client;
		newLink.flag = 0;
		KeyObj_Client _linkInfo(client->get_peer_ip(),10001);
		m_MyMutex.Lock();
		std::map<KeyObj_Client, ClientSOCKET_ACL>::iterator it_client =	m_CSockets.find(_linkInfo);
		if(it_client!=m_CSockets.end()){
			close_client(it_client->second.client);
		}
		m_CSockets[_linkInfo] = newLink;//
		m_MyMutex.Unlock();
		newlinkF = true;
		CLogger::createInstance()->Log(MsgInfo,
			"Connect Accept Success: %s,[%s %s %d]"
			, client->get_peer(true), __FILE__, __FUNCTION__, __LINE__);
		return true;
	}
	return false;
}